package pyip.lib.javalearn.thread.future;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * @author yepeng
 * @date 2015年4月23日
 */
public class ExecutorTest {

    @Before
    public void before() {
        System.out.println("main start");
    }

    @After
    public void after() {
        System.out.println("main exit");
    }

    @Test
    public void testInterrupt() {
        FutureTask<String> future = new FutureTask<String>(new TestCallable());
        Thread t1 = new Thread(future);
        t1.start();

        try {
            Thread.sleep(1000);
            System.out.println("interrupt t1");
            t1.interrupt();
            System.out.println("get t1 future");
            String result = future.get(1, TimeUnit.SECONDS);
            System.out.println("result from t1: " + result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCancelTrue() {
        FutureTask<String> future = new FutureTask<String>(new TestCallable());
        Thread t1 = new Thread(future);
        t1.start();

        try {
            Thread.sleep(1000);
            System.out.println("cancel t1 future");
            future.cancel(true);
            if (!future.isCancelled()) {
                System.out.println("get t1 future");
                String result = future.get(1, TimeUnit.SECONDS);
                System.out.println("result from t1: " + result);
            } else {
                System.out.println("future.isCancelled: " + future.isCancelled());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCancelFalse() {
        FutureTask<String> future = new FutureTask<String>(new TestCallable());
        Thread t1 = new Thread(future);
        t1.start();

        try {
            Thread.sleep(1000);
            System.out.println("cancel t1 future");
            future.cancel(false);
            if (!future.isCancelled()) {
                System.out.println("get t1 future");
                String result = future.get(1, TimeUnit.SECONDS);
                System.out.println("result from t1: " + result);
            } else {
                System.out.println("future.isCancelled: " + future.isCancelled());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCancelGet() {
        FutureTask<String> future = new FutureTask<String>(new TestCallable());
        Thread t1 = new Thread(future);
        t1.start();

        try {
            Thread.sleep(1000);
            System.out.println("cancel t1 future");
            future.cancel(true);
            System.out.println("get t1 future");
            String result = future.get(1, TimeUnit.SECONDS);
            System.out.println("result from t1: " + result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testTimeOut() {
        FutureTask<String> future = new FutureTask<String>(new TestCallable());
        Thread t1 = new Thread(future);
        t1.start();

        try {
            Thread.sleep(1000);
            System.out.println("get t1 future");
            String result = future.get(1, TimeUnit.SECONDS);
            System.out.println("result from t1: " + result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            System.out.println("get timeOutException");
            try {
                System.out.println("sleep 10s");
                Thread.sleep(10000);
                System.out.println("get t1 future again");
                String result = future.get(1, TimeUnit.SECONDS);
                System.out.println("result from t1: " + result);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            } catch (ExecutionException e1) {
                e1.printStackTrace();
            } catch (TimeoutException e1) {
                e1.printStackTrace();
            }
        }
    }

    @Test
    public void testShutdownNow() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(new TestCallable());
        executorService.shutdownNow();

        // try {
        // Thread.sleep(2000);
        // } catch (InterruptedException e) {
        // e.printStackTrace();
        // }
    }

}

class TestCallable implements Callable<String> {

    public String call() throws Exception {
        System.out.println("\tt1 start");

        for (int i = 0; i < 10; i++) {
            try {
                System.out.println("\tt1 sleep");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("\tt1 exit interrupted");
                return "interrupt";
            }

            // if (Thread.interrupted()) {
            // return "interrupt";
            // }
        }

        System.out.println("\tt1 exit normal");
        return "success";
    }
}
